﻿#pragma once

#if defined(DEBUG) || defined(_DEBUG)
#define OBJECT_SYSTEM_DEBUG
#endif

#include <string>
#include <memory>
#include <cstdint>
#include <thread>
#include <sstream>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>

namespace kratos {
namespace object_system {

struct ObjectSystem;
template <typename T>
struct ObjectRef;
template <typename ObjectTypeT>
struct UniqueRef;

// 获取当前线程ID
extern std::thread::id get_thread_id();
// 获取所有已分配但还未标记为释放状态的对象
extern void dump(std::ostream& os);
// 获取活跃对象数量
extern std::size_t get_alive_object_count();
// 获取等待销毁的对象数量
extern std::size_t get_dispose_object_count();

// 对象
class Object {
private:
	// 对象状态
	enum class ObjectState : std::int8_t {
		state_alive = 1, ///< 正常存活
		state_dispose, ///< 废弃不可使用
	};
#ifdef OBJECT_SYSTEM_DEBUG
	std::string file_; ///< 分配对象所在源文件
	int line_; ///< 分配对象所在源文件行号
#endif

public:
#ifdef OBJECT_SYSTEM_DEBUG
	// 构造一个对象
	// @param type_info 关联对象的type_info
	// @param tid 建立对象的线程ID
	// @param file 文件名
	// @param line 行号
	Object(const std::type_info& type_info, std::thread::id tid, const std::string& file, int line);
#else
	// 构造一个对象
	// @param type_info 关联对象的type_info
	// @param tid 建立对象的线程ID
	Object(const std::type_info& type_info, std::thread::id tid);
#endif
	// 析构
	virtual ~Object();
	// 将对象设置为销毁状态ObjectState::state_dispose
	// @retval true 销毁成功
	// @retval false 销毁失败
	auto dispose()->bool;
	// 检测对象是否处于ObjectState::state_alive
	// @retval true 对象处于ObjectState::state_alive状态
	// @retval false 对象不能访问
	auto is_alive()->bool;
	// 获取对象ID
	auto id()->std::uint64_t;
	// 获取对象所属的线程ID
	auto thread_id()->std::thread::id;
	// 对象线程模式
	enum class ThreadMode {
		mode_single = 1, ///< 单线程对象
		mode_multi, ///< 多线程对象
	};
	// 获取对象线程模式
	ThreadMode get_thread_mode() const;
	// 获取对象分配发生的源代码文件
	auto get_file_name() const -> const std::string&;
	// 获取对象分配发生的源文件代码行
	auto get_line() const -> int;
	// 获取std::type_info
	auto type_info() const -> const std::type_info&;

private:
	const std::type_info& type_info_; ///< std::type_info
	std::uint64_t id_{ 0 }; ///< 对象ID
	ObjectState lifecycle_state_{ ObjectState::state_alive }; ///< 对象状态
	std::thread::id tid_; ///< 分配对象的线程ID
	ThreadMode thread_mode_{ ThreadMode::mode_single }; ///< 对象的线程模式
	void set_thread_mode(ThreadMode thread_mode); ///< 设置对象的线程模式

#ifdef OBJECT_SYSTEM_DEBUG
	template <typename ObjectTypeT, typename...ArgsT>
	friend auto new_object(const std::string& file, int line, ArgsT...args)->ObjectRef<ObjectTypeT>;

	template <typename ObjectTypeT, typename...ArgsT>
	friend auto new_object_multithread(const std::string& file, int line, ArgsT...args)->ObjectRef<ObjectTypeT>;
#else
	template <typename ObjectTypeT, typename...ArgsT>
	friend auto new_object(ArgsT...args)->ObjectRef<ObjectTypeT>;

	template <typename ObjectTypeT, typename...ArgsT>
	friend auto new_object_multithread(ArgsT...args)->ObjectRef<ObjectTypeT>;
#endif
};

// 对象系统内部使用的胶水类，用来衔接用户对象和Object
template <typename ObjectTypeT, typename...ArgsT>
class ObjectGeneric : public ObjectTypeT, public Object {
public:
#ifdef OBJECT_SYSTEM_DEBUG
	ObjectGeneric(const std::string& file, int line, ArgsT...args)
		: ObjectTypeT(args...), Object(typeid(ObjectTypeT), get_thread_id(), file, line) {}
#else
	ObjectGeneric(ArgsT...args) : ObjectTypeT(args...), Object(typeid(ObjectTypeT), get_thread_id()) {}
#endif
	virtual ~ObjectGeneric() {}
};

// 对象引用, 用户所使用的对象引用, 作为实际对象的观察者
template <typename T>
struct ObjectRef {
private:
	std::weak_ptr<T> ob_; ///< std::weak_ptr
	std::uint64_t id_{ 0 }; ///< 对象ID
	std::thread::id tid_; ///< 建立对象的线程ID
	Object::ThreadMode thread_mode_{ Object::ThreadMode::mode_single }; ///< 对象的线程模式
	const std::type_info* type_info_{ nullptr }; ///< std::type_info
#ifdef OBJECT_SYSTEM_DEBUG
	std::string file_; ///< 调试信息,建立对象所在源文件名
	int line_{ 0 }; ///< 调试信息,建立对象所在的源文件行号
#endif
#ifdef OBJECT_SYSTEM_DEBUG
	explicit ObjectRef(std::weak_ptr<T> ob, std::uint64_t id, std::thread::id tid, Object::ThreadMode thread_mode,
		const std::string& file, int line) noexcept : type_info_(&typeid(T)) {
		if (ob.expired()) {
			return;
		}
		ob_ = ob;
		id_ = id;
		tid_ = tid;
		thread_mode_ = thread_mode;
		file_ = file;
		line_ = line;
	}
#else
	explicit ObjectRef(std::weak_ptr<T> ob, std::uint64_t id, std::thread::id tid, Object::ThreadMode thread_mode) noexcept
		: type_info_(&typeid(T)) {
		if (ob.expired()) {
			return;
		}
		ob_ = ob;
		id_ = id;
		tid_ = tid;
		thread_mode_ = thread_mode;
	}
#endif

	auto thread_check() const noexcept->bool {
		if (thread_mode_ == Object::ThreadMode::mode_single) {
			if (tid_ != get_thread_id()) {
				return false;
			}
		}
		return true;
	}

	void throw_exception(const ObjectRef<T>& ref) const {
		std::stringstream ss;
		ss << "[对象系统]对象已经无效, 对象分配信息:(" << ref.get_file_name() << ","
			<< ref.get_line() << ")";
		throw std::runtime_error(ss.str());
	}

	ObjectRef<T>* operator&() = delete;
	ObjectRef<T>* operator&() const = delete;

public:
	ObjectRef() noexcept {}
	ObjectRef(const ObjectRef<T>& ref) noexcept {
		ob_ = ref.ob_;
		id_ = ref.id_;
		tid_ = ref.tid_;
		thread_mode_ = ref.thread_mode_;
		type_info_ = ref.type_info_;
#ifdef OBJECT_SYSTEM_DEBUG
		file_ = ref.file_;
		line_ = ref.line_;
#endif
	}
	ObjectRef(ObjectRef&& ref) noexcept {
		ob_ = ref.ob_;
		id_ = ref.id_;
		tid_ = ref.tid_;
		thread_mode_ = ref.thread_mode_;
        type_info_ = ref.type_info_;
		ref.ob_.reset();
		ref.id_ = 0;
#ifdef OBJECT_SYSTEM_DEBUG
		file_ = ref.file_;
		line_ = ref.line_;
#endif
	}
	const ObjectRef& operator=(const ObjectRef& ref) noexcept {
		id_ = ref.id_;
		ob_ = ref.ob_;
		tid_ = ref.tid_;
		thread_mode_ = ref.thread_mode_;
        type_info_ = ref.type_info_;
#ifdef OBJECT_SYSTEM_DEBUG
		file_ = ref.file_;
		line_ = ref.line_;
#endif
		return *this;
	}
	const ObjectRef& operator=(ObjectRef&& ref) noexcept {
		ob_ = ref.ob_;
		id_ = ref.id_;
		tid_ = ref.tid_;
		thread_mode_ = ref.thread_mode_;
        type_info_ = ref.type_info_;
		ref.ob_.reset();
		ref.id_ = 0;
#ifdef OBJECT_SYSTEM_DEBUG
		file_ = ref.file_;
		line_ = ref.line_;
#endif
		return *this;
	}
	bool operator==(const ObjectRef& ref) const noexcept {
		return (id_ == ref.id_);
	}
	bool operator==(std::uint64_t id) const noexcept {
		return (id_ == id);
	}
	bool operator!=(const ObjectRef& ref) const noexcept {
		return (id_ != ref.id_);
	}
	bool operator<(const ObjectRef& ref) const noexcept {
		return (id_ < ref.id_);
	}
	bool operator>(const ObjectRef& ref) const noexcept {
		return (id_ > ref.id_);
	}
	bool operator<=(const ObjectRef& ref) const noexcept {
		return (id_ <= ref.id_);
	}
	bool operator>=(const ObjectRef& ref) const noexcept {
		return (id_ >= ref.id_);
	}
	bool operator!=(std::uint64_t id) const noexcept {
		return (id_ != id);
	}
	bool operator<(std::uint64_t id) const noexcept {
		return (id_ < id);
	}
	bool operator>(std::uint64_t id) const noexcept {
		return (id_ > id);
	}
	bool operator<=(std::uint64_t id) const noexcept {
		return (id_ <= id);
	}
	bool operator>=(std::uint64_t id) const noexcept {
		return (id_ >= id);
	}
	bool dispose() noexcept {
		if (ob_.expired()) {
			return false;
		}
		if (!thread_check()) {
			// 单线程对象，不能多线程释放
			return false;
		}
		auto objptr = std::dynamic_pointer_cast<Object>(ob_.lock());
		if (!objptr) {
			return false;
		}
		return objptr->dispose();
	}
	bool dispose() const noexcept {
		if (ob_.expired()) {
			return false;
		}
		if (!thread_check()) {
			// 单线程对象，不能多线程释放
			return false;
		}
		auto objptr = std::dynamic_pointer_cast<Object>(ob_.lock());
		if (!objptr) {
			return false;
		}
		return objptr->dispose();
	}

	operator bool() noexcept {
		if (ob_.expired()) {
			return false;
		}
		auto objptr = std::dynamic_pointer_cast<Object>(ob_.lock());
		if (!objptr) {
			return false;
		}
		return objptr->is_alive();
	}

	operator bool() const noexcept {
		if (ob_.expired()) {
			return false;
		}
		auto objptr = std::dynamic_pointer_cast<Object>(ob_.lock());
		if (!objptr) {
			return false;
		}
		return objptr->is_alive();
	}

	operator std::uint64_t() const noexcept {
		return id_;
	}
	operator std::string() noexcept {
		return std::to_string(id_);
	}
	operator const std::string() const noexcept {
		return std::to_string(id_);
	}
	T* operator->() {
		if (!*this) {
			throw_exception(*this);
		}
		if (!thread_check()) {
			throw std::runtime_error("单线程对象在非所有者线程访问");
		}
		return ob_.lock().get();
	}
	const T* operator->() const {
		if (!*this) {
			throw_exception(*this);
		}
		if (!thread_check()) {
			throw std::runtime_error("单线程对象在非所有者线程访问");
		}
		return ob_.lock().get();
	}
	const T& operator*() const {
		if (!*this) {
			throw_exception(*this);
		}
		if (!thread_check()) {
			throw std::runtime_error("单线程对象在非所有者线程访问");
		}
		return *ob_.lock().get();
	}
	T& operator*() {
		if (!*this) {
			throw_exception(*this);
		}
		if (!thread_check()) {
			throw std::runtime_error("单线程对象在非所有者线程访问");
		}
		return *ob_.lock().get();
	}
	const std::type_info* type_info() noexcept {
		return type_info_;
	}
	std::uint64_t id() const noexcept {
		return id_;
	}
	std::thread::id thread_id() const noexcept {
		return tid_;
	}
#ifdef OBJECT_SYSTEM_DEBUG
	auto get_file_name() const noexcept -> const std::string& {
		return file_;
	}
	auto get_line() const noexcept -> int {
		return line_;
	}
#else
	auto get_file_name() const noexcept -> const std::string& {
		static std::string null;
		return null;
	}
	auto get_line() const noexcept -> int {
		return 0;
	}
#endif

	void reset() {
		ob_.reset();
	}

	template <typename ObjectTypeT>
	friend auto get_object(std::uint64_t id)->ObjectRef<ObjectTypeT>;

	template <typename OtherT, typename ObjectTypeT>
	friend ObjectRef<OtherT> dynamic_cast_ref(ObjectRef<ObjectTypeT>& ref);

	template <typename OtherT, typename ObjectTypeT>
	friend ObjectRef<OtherT> dynamic_cast_ref(ObjectRef<ObjectTypeT>&& ref);

	template <typename OtherT, typename ObjectTypeT>
	friend ObjectRef<OtherT> static_cast_ref(ObjectRef<ObjectTypeT>& ref);

	template <typename OtherT, typename ObjectTypeT>
	friend ObjectRef<OtherT> static_cast_ref(ObjectRef<ObjectTypeT>&& ref);

	template <typename OtherT, typename ObjectTypeT>
	friend ObjectRef<OtherT> const_cast_ref(const ObjectRef<ObjectTypeT>& ref);

	template <typename OtherT, typename ObjectTypeT>
	friend ObjectRef<OtherT> reinterpret_cast_ref(const ObjectRef<T>& ref);

	template <typename OtherT, typename ObjectTypeT>
	friend ObjectRef<OtherT> reinterpret_cast_ref(ObjectRef<T>&& ref);

#ifdef OBJECT_SYSTEM_DEBUG
	template <typename ObjectTypeT, typename...ArgsT>
	friend auto new_object(const std::string& file, int line, ArgsT...args)->ObjectRef<ObjectTypeT>;

	template <typename ObjectTypeT, typename...ArgsT>
	friend auto new_object_multithread(const std::string& file, int line, ArgsT...args)->ObjectRef<ObjectTypeT>;
#else
	template <typename ObjectTypeT, typename...ArgsT>
	friend auto new_object(ArgsT...args)->ObjectRef<ObjectTypeT>;

	template <typename ObjectTypeT, typename...ArgsT>
	friend auto new_object_multithread(ArgsT...args)->ObjectRef<ObjectTypeT>;
#endif

	template <typename ObjectTypeT>
	friend struct ScopeRef;
};

template <typename OtherT, typename T>
ObjectRef<OtherT> dynamic_cast_ref(ObjectRef<T>& ref) {
	auto objptr = std::dynamic_pointer_cast<OtherT>(ref.ob_.lock());
#ifdef OBJECT_SYSTEM_DEBUG
	ObjectRef<OtherT> other_ref(std::weak_ptr<OtherT>(objptr), ref.id_, ref.tid_, ref.thread_mode_, ref.file_, ref.line_);
#else
	ObjectRef<OtherT> other_ref(std::weak_ptr<OtherT>(objptr), ref.id_, ref.tid_, ref.thread_mode_);
#endif
	return other_ref;
}

template <typename OtherT, typename ObjectTypeT>
ObjectRef<OtherT> static_cast_ref(ObjectRef<ObjectTypeT>& ref) {
	auto objptr = std::static_pointer_cast<OtherT>(ref.ob_.lock());
#ifdef OBJECT_SYSTEM_DEBUG
	ObjectRef<OtherT> other_ref(std::weak_ptr<OtherT>(objptr), ref.id_, ref.tid_, ref.thread_mode_, ref.file_, ref.line_);
#else
	ObjectRef<OtherT> other_ref(std::weak_ptr<OtherT>(objptr), ref.id_, ref.tid_, ref.thread_mode_);
#endif
	return other_ref;
}

template <typename OtherT, typename T>
ObjectRef<OtherT> dynamic_cast_ref(ObjectRef<T>&& ref) {
	auto objptr = std::dynamic_pointer_cast<OtherT>(ref.ob_.lock());
#ifdef OBJECT_SYSTEM_DEBUG
	ObjectRef<OtherT> other_ref(std::weak_ptr<OtherT>(objptr), ref.id_, ref.tid_, ref.thread_mode_, ref.file_, ref.line_);
#else
	ObjectRef<OtherT> other_ref(std::weak_ptr<OtherT>(objptr), ref.id_, ref.tid_, ref.thread_mode_);
#endif
	return other_ref;
}

template <typename OtherT, typename ObjectTypeT>
ObjectRef<OtherT> static_cast_ref(ObjectRef<ObjectTypeT>&& ref) {
	auto objptr = std::static_pointer_cast<OtherT>(ref.ob_.lock());
#ifdef OBJECT_SYSTEM_DEBUG
	ObjectRef<OtherT> other_ref(std::weak_ptr<OtherT>(objptr), ref.id_, ref.tid_, ref.thread_mode_, ref.file_, ref.line_);
#else
	ObjectRef<OtherT> other_ref(std::weak_ptr<OtherT>(objptr), ref.id_, ref.tid_, ref.thread_mode_);
#endif
	return other_ref;
}

template <typename OtherT, typename ObjectTypeT>
ObjectRef<OtherT> const_cast_ref(const ObjectRef<ObjectTypeT>& ref) {
	auto objptr = std::const_pointer_cast<OtherT>(ref.ob_.lock());
#ifdef OBJECT_SYSTEM_DEBUG
	ObjectRef<OtherT> other_ref(std::weak_ptr<OtherT>(objptr), ref.id_, ref.tid_, ref.thread_mode_, ref.file_, ref.line_);
#else
	ObjectRef<OtherT> other_ref(std::weak_ptr<OtherT>(objptr), ref.id_, ref.tid_, ref.thread_mode_);
#endif
	return other_ref;
}

/*
template <typename OtherT, typename T>
ObjectRef<OtherT> reinterpret_cast_ref(const ObjectRef<T>& ref) {
	auto objptr = std::reinterpret_pointer_cast<OtherT>(ref.ob_.lock());
#ifdef OBJECT_SYSTEM_DEBUG
	ObjectRef<OtherT> other_ref(std::weak_ptr<OtherT>(objptr), ref.id_, ref.tid_, ref.thread_mode_, ref.file_, ref.line_);
#else
	ObjectRef<OtherT> other_ref(std::weak_ptr<OtherT>(objptr), ref.id_, ref.tid_, ref.thread_mode_);
#endif
	return other_ref;
}

template <typename OtherT, typename T>
ObjectRef<OtherT> reinterpret_cast_ref(ObjectRef<T>&& ref) {
	auto objptr = std::reinterpret_pointer_cast<OtherT>(ref.ob_.lock());
#ifdef OBJECT_SYSTEM_DEBUG
	ObjectRef<OtherT> other_ref(std::weak_ptr<OtherT>(objptr), ref.id_, ref.tid_, ref.thread_mode_, ref.file_, ref.line_);
#else
	ObjectRef<OtherT> other_ref(std::weak_ptr<OtherT>(objptr), ref.id_, ref.tid_, ref.thread_mode_);
#endif
	return other_ref;
}*/

// 内部使用的对象系统，对用户不可见
struct ObjectSystem {
	ObjectSystem() = delete;
	ObjectSystem(const ObjectSystem&) = delete;
	ObjectSystem(ObjectSystem&&) = delete;
	const ObjectSystem& operator=(const ObjectSystem&) = delete;
	const ObjectSystem& operator=(ObjectSystem&&) = delete;

private:
	// 添加一个新的对象
	// @param object 对象指针
	// @return 智能指针对象
	static auto add_object(Object* object)->std::shared_ptr<Object>;
	// 销毁对象
	// @param id 对象ID
	// @param tid 对象所属的线程ID
	// @retval true 成功
	// @retval false 失败
	static auto dispose_object(std::uint64_t id, std::thread::id tid)->bool;
	// 获取对象
	// @param id 对象ID
	// @return 智能指针对象
	static auto get_object(std::uint64_t id)->std::shared_ptr<Object>;
	// 生成一个新的对象ID
	static auto new_id()->std::uint64_t;

	friend class Object;

	template <typename ObjectTypeT>
	friend auto get_object(std::uint64_t id)->ObjectRef<ObjectTypeT>;

#ifdef OBJECT_SYSTEM_DEBUG
	template <typename ObjectTypeT, typename...ArgsT>
	friend auto new_object(const std::string& file, int line, ArgsT...args)->ObjectRef<ObjectTypeT>;

	template <typename ObjectTypeT, typename...ArgsT>
	friend auto new_object_multithread(const std::string& file, int line, ArgsT...args)->ObjectRef<ObjectTypeT>;
#else
	template <typename ObjectTypeT, typename...ArgsT>
	friend auto new_object(ArgsT...args)->ObjectRef<ObjectTypeT>;

	template <typename ObjectTypeT, typename...ArgsT>
	friend auto new_object_multithread(ArgsT...args)->ObjectRef<ObjectTypeT>;
#endif
};

#ifdef OBJECT_SYSTEM_DEBUG
// 生成一个单线程对象
template <typename ObjectTypeT, typename...ArgsT>
auto new_object(const std::string& file, int line, ArgsT...args)->ObjectRef<ObjectTypeT> {
	auto raw_ptr = new ObjectGeneric<ObjectTypeT, ArgsT... >(file, line, std::forward<ArgsT>(args)...);
	raw_ptr->set_thread_mode(Object::ThreadMode::mode_single);
	auto id = raw_ptr->id();
	auto objptr = ObjectSystem::add_object(raw_ptr);
	return ObjectRef<ObjectTypeT>(std::dynamic_pointer_cast<ObjectTypeT>(objptr), id, get_thread_id(),
		Object::ThreadMode::mode_single, file, line);
}
#else
// 生成一个单线程对象
template <typename ObjectTypeT, typename...ArgsT>
auto new_object(ArgsT...args)->ObjectRef<ObjectTypeT> {
	auto raw_ptr = new ObjectGeneric<ObjectTypeT, ArgsT... >(std::forward<ArgsT>(args)...);
	raw_ptr->set_thread_mode(Object::ThreadMode::mode_single);
	auto id = raw_ptr->id();
	auto objptr = ObjectSystem::add_object(raw_ptr);
	return ObjectRef<ObjectTypeT>(std::dynamic_pointer_cast<ObjectTypeT>(objptr), id, get_thread_id(),
		Object::ThreadMode::mode_single);
}
#endif

#ifdef OBJECT_SYSTEM_DEBUG
	#define spawn_object(ObjectType, ...) \
		new_object<ObjectType>(__FILE__, __LINE__, __VA_ARGS__)
#else
	#define spawn_object(ObjectType, ...) \
		new_object<ObjectType>(__VA_ARGS__)
#endif // OBJECT_SYSTEM_DEBUG


#ifdef OBJECT_SYSTEM_DEBUG
// 生成一个多线程对象
template <typename ObjectTypeT, typename...ArgsT>
auto new_object_multithread(const std::string& file, int line, ArgsT...args)->ObjectRef<ObjectTypeT> {
	auto raw_ptr = new ObjectGeneric<ObjectTypeT, ArgsT... >(file, line, std::forward<ArgsT>(args)...);
	raw_ptr->set_thread_mode(Object::ThreadMode::mode_multi);
	auto id = raw_ptr->id();
	auto objptr = ObjectSystem::add_object(raw_ptr);
	return ObjectRef<ObjectTypeT>(std::dynamic_pointer_cast<ObjectTypeT>(objptr), id, get_thread_id(),
		Object::ThreadMode::mode_multi, file, line);
}
#else
// 生成一个多线程对象
template <typename ObjectTypeT, typename...ArgsT>
auto new_object_multithread(ArgsT...args)->ObjectRef<ObjectTypeT> {
	auto raw_ptr = new ObjectGeneric<ObjectTypeT, ArgsT... >(std::forward<ArgsT>(args)...);
	raw_ptr->set_thread_mode(Object::ThreadMode::mode_multi);
	auto id = raw_ptr->id();
	auto objptr = ObjectSystem::add_object(raw_ptr);
	return ObjectRef<ObjectTypeT>(std::dynamic_pointer_cast<ObjectTypeT>(objptr), id, get_thread_id(),
		Object::ThreadMode::mode_multi);
}
#endif

#ifdef OBJECT_SYSTEM_DEBUG
#define spawn_object_multithread(ObjectType, ...) \
		new_object_multithread<ObjectType>(__FILE__, __LINE__, __VA_ARGS__)
#else
#define spawn_object_multithread(ObjectType, ...) \
		new_object_multithread<ObjectType>(__VA_ARGS__)
#endif // OBJECT_SYSTEM_DEBUG

// 在当前线程内获取对象
// @param id 对象ID
template <typename ObjectTypeT>
auto get_object(std::uint64_t id)->ObjectRef<ObjectTypeT> {
	auto objptr = ObjectSystem::get_object(id);
	if (!objptr) {
		return ObjectRef<ObjectTypeT>();
	}
#ifdef OBJECT_SYSTEM_DEBUG
	return ObjectRef<ObjectTypeT>(std::dynamic_pointer_cast<ObjectTypeT>(objptr), objptr->id(), get_thread_id(),
		objptr->get_thread_mode(), objptr->get_file_name(), objptr->get_line());
#else
	return ObjectRef<ObjectTypeT>(std::dynamic_pointer_cast<ObjectTypeT>(objptr), objptr->id(), get_thread_id(),
		objptr->get_thread_mode());
#endif
}

template <typename T>
using object_set = std::set<ObjectRef<T>>;

template <typename T>
struct MapCmp {
	bool operator()(const ObjectRef<T>& a, const ObjectRef<T>& b) const noexcept {
		return (a.id() < b.id());
	}
};

template <typename T, typename V>
using object_map = std::map<ObjectRef<T>, V, MapCmp<T>>;

template <typename T>
struct SetEqual {
	bool operator()(const ObjectRef<T>& a, const ObjectRef<T>& b) const noexcept {
		return (a.id() == b.id());
	}
};

template <typename T>
struct SetHasher {
	std::uint64_t operator()(const ObjectRef<T>& a) const noexcept {
		return a.id();
	}
};

template <typename T, typename V>
using object_unordered_map = std::unordered_map<ObjectRef<T>, V, SetHasher<T>, SetEqual<T>>;

template <typename T>
using object_unordered_set = std::unordered_set<ObjectRef<T>, SetHasher<T>, SetEqual<T>>;

// 自动释放对象的包装类，防止未调用ObjectRef::dispose导致的内存泄露
template <typename ObjectTypeT>
struct UniqueRef {
private:
	ObjectRef<ObjectTypeT> ref_; ///< 实际持有的引用对象 
	UniqueRef<ObjectTypeT>* operator&() = delete;
	UniqueRef<ObjectTypeT>* operator&() const = delete;
public:
	UniqueRef() {}
	// 所持有对象类型的构造包装，提高使用便利性
	template<typename...ArgsT>
	UniqueRef(Object::ThreadMode mode, ArgsT...args) {
		if (mode == Object::ThreadMode::mode_single) {
			ref_ = spawn_object(ObjectTypeT, args...);
		} else if (mode == Object::ThreadMode::mode_multi) {
			ref_ = spawn_object_multithread(ObjectTypeT, args...);
		} else {
			throw std::runtime_error("Invalid mode");
		}
	}
	UniqueRef(const UniqueRef& rht) noexcept {
		ref_ = rht.ref_;
	}
	UniqueRef(UniqueRef&& rht) noexcept {
		ref_ = rht.ref_;
		rht.ref_.reset();
	}
	explicit UniqueRef(const ObjectRef<ObjectTypeT>& ref) noexcept {
		ref_ = ref;
	}
	UniqueRef(ObjectRef<ObjectTypeT>&& ref) noexcept {
		ref_ = ref;
		ref.reset();
	}
	const UniqueRef& operator=(const UniqueRef& rht) noexcept {
		if (ref_ && (ref_ == rht.ref_)) {
			return *this;
		}
		if (ref_) {
			ref_.dispose();
		}
		ref_ = rht.ref_;
		return *this;
	}
	const UniqueRef& operator=(UniqueRef&& rht) noexcept {
		if (ref_ && (ref_ == rht.ref_)) {
			return *this;
		}
		if (ref_) {
			ref_.dispose();
		}
		ref_ = rht.ref_;
		rht.ref_.reset();
		return *this;
	}
	const UniqueRef& operator=(const ObjectRef<ObjectTypeT>& ref) noexcept {
		if (ref_ && (ref_ == ref)) {
			return *this;
		}
		if (ref_) {
			ref_.dispose();
		}
		ref_ = ref;
		return *this;
	}
	const UniqueRef& operator=(ObjectRef<ObjectTypeT>&& ref) noexcept {
		if (ref_ && (ref_ == ref)) {
			return *this;
		}
		if (ref_) {
			ref_.dispose();
		}
		ref_ = ref;
		ref.reset();
		return *this;
	}
	~UniqueRef() noexcept {
		if (ref_) {
			ref_.dispose();
		}
	}
	void reset(ObjectRef<ObjectTypeT>&& ref) noexcept {
		if (ref_ == ref) {
			return;
		}
		if (ref_) {
			ref_.dispose();
		}
		ref_ = ref;
		ref.reset();
	}
	void reset(const ObjectRef<ObjectTypeT>& ref) noexcept {
		if (ref_ == ref) {
			return;
		}
		if (ref_) {
			ref_.dispose();
		}
		ref_ = ref;
	}
	void reset() noexcept {
		if (ref_) {
			ref_.dispose();
		}
	}
	ObjectRef<ObjectTypeT>& get() noexcept {
		return ref_;
	}
	const ObjectRef<ObjectTypeT>& get() const noexcept {
		return ref_;
	}
	operator bool() noexcept {
		return (bool)ref_;
	}
	operator bool() const noexcept {
		return (bool)ref_;
	}
};

template <typename T>
using unique_object_set = std::set<UniqueRef<T>>;

template <typename T>
struct UniqueMapCmp {
	bool operator()(const UniqueRef<T>& a, const UniqueRef<T>& b) const noexcept {
		return (a.get().id() < a.get().id());
	}
};

template <typename T, typename V>
using unique_object_map = std::map<UniqueRef<T>, V, UniqueMapCmp<T>>;

template <typename T>
struct UniqueSetEqual {
	bool operator()(const UniqueRef<T>& a, const UniqueRef<T>& b) const noexcept {
		return (a.get().id() == b.get().id());
	}
};

template <typename T>
struct UniqueSetHasher {
	std::uint64_t operator()(const UniqueRef<T>& a) const noexcept {
		return a.get().id();
	}
};

template <typename T, typename V>
using unique_object_unordered_map = std::unordered_map<UniqueRef<T>, V, UniqueSetHasher<T>, UniqueSetEqual<T>>;

template <typename T>
using unique_object_unordered_set = std::unordered_set<UniqueRef<T>, UniqueSetHasher<T>, UniqueSetEqual<T>>;

}
}
